package gui;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;

import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JPanel;

/**
 * @author Ramy Refky 
 * */
public class WorkArea extends JPanel implements MouseListener,MouseMotionListener{ 
	
	private static final long serialVersionUID = 1L;
	
	MainGui mg;
	WiringGrid wiringGrid;
	
	Point selectionBoxStartPoint;
	Point selectionBoxEndPoint;
	Rectangle selectionBox;
	Point dragStartPoint;
	Point dragEndPoint;
	Point mousePoint;   
	ArrayList<ComponentGraphics> addedComponents;
	ArrayList<WireSegment> wireSegments;
	ArrayList<WireIntersectionPoint> wireIntersectionPoints;
	ArrayList<WireGroupDisplay> wireGroupDisplays;
	boolean showGrid;
	
	/**
	 * Constructor initializes WorkArea.
	 * @param MainGui
	 * */
	public WorkArea(MainGui mg){

		this.mg=mg;
		wiringGrid= new WiringGrid(mg);
		
		addedComponents = new ArrayList<ComponentGraphics>();
		wireSegments = new ArrayList<WireSegment>();
		wireIntersectionPoints = new ArrayList<WireIntersectionPoint>();
		wireGroupDisplays = new ArrayList<WireGroupDisplay>();
		
		setBounds(0,0,1500,1500);
		this.setBackground(Color.white);
		setVisible(true);
		setLayout(null);
		
		selectionBox = new Rectangle();
    	selectionBoxStartPoint=new Point();
    	selectionBoxEndPoint=new Point();
    	dragStartPoint=new Point();
    	dragEndPoint=new Point();
    	mousePoint=new Point();
    	showGrid=true;
    	
    	addMouseMotionListener(this);
    	addMouseListener(this);
		repaint();
		validate();
	}
	/**
	 * Adds and displays a given WireSegment onto the WorkArea.
	 * */
	public void addWireSegment(WireSegment ws){
		
		wireSegments.add(ws);
		this.add(wireSegments.get(wireSegments.size()-1));
		this.setComponentZOrder(wireSegments.get(wireSegments.size()-1),getComponentCount()-1);
		repaint();
	}
	/**
	 * Removes a displayed wire from the WorkArea.
	 * */
	public void removeWire(Wire w){
		
		for(int i=0;i<wireSegments.size();i++){
			if(w.equals(wireSegments.get(i).getWire())){
				this.remove(wireSegments.get(i));
				wireSegments.remove(i);
				i--;
				repaint();
			}
		}
	}
	/**
	 * Adds and displays a WireIntersectionPoint onto the WorkArea, given a certain point.
	 * */
	public void addWireIntersectionPoint(Point drawPoint){
		Point p= new Point(drawPoint.x-4,drawPoint.y-4);
		WireIntersectionPoint wp = new WireIntersectionPoint(p);
		wireIntersectionPoints.add(wp);
		this.add(wireIntersectionPoints.get(wireIntersectionPoints.size()-1));
		this.setComponentZOrder(wireIntersectionPoints.get(wireIntersectionPoints.size()-1),getComponentCount()-1);
	}
	/**
	 * Adds and displays a WireGroupDisplay onto the WorkArea.
	 * */
	public void addWireGroupDisplay(int x,int y, int groupedCount){
		
		WireGroupDisplay wg = new WireGroupDisplay(x,y,groupedCount);
		wireGroupDisplays.add(wg);
		this.add(wireGroupDisplays.get(wireGroupDisplays.size()-1));
		this.setComponentZOrder(wireGroupDisplays.get(wireGroupDisplays.size()-1),getComponentCount()-1);
	}
	/**
	 * Removes all WireIntersectionPoints from the WorkArea.
	 * */
	public void removeAllWireIntersections(){
		for(int i=0;i<wireIntersectionPoints.size();i++){
			this.remove(wireIntersectionPoints.get(i));
		}
		for(int i=0;i<wireIntersectionPoints.size();i++){
			wireIntersectionPoints.remove(i);
		}
	}
	/**
	 * Removes all WireGroupDisplays from the WorkArea.
	 * */
	public void removeAllWireGroupDisplays(){
		for(int i=0;i<wireGroupDisplays.size();i++){
			this.remove(wireGroupDisplays.get(i));
		}
		for(int i=0;i<wireGroupDisplays.size();i++){
			wireGroupDisplays.remove(i);
		}
	}
	/**
	 * Removes a displayed component from the WorkArea.
	 * */
	public void deleteComponent(ComponentGraphics cg){
		for(int i=0;i<cg.getInputPins().size();i++){
			mg.getWorkArea().getWiringGrid().deleteWire(cg.getInputPins().get(i));
		}
		for(int i=0;i<cg.getOutputPins().size();i++){
			mg.getWorkArea().getWiringGrid().deleteWire(cg.getOutputPins().get(i));
		}
		this.remove(cg);
		addedComponents.remove(cg);
	}
	/**
	 * Adds an AND Gate onto the WorkArea.
	 * */
	public void addAndComponent(int x,int y, int w, int h,int numOfInputs){
		AndComponentGraphics ac =new AndComponentGraphics(mg,x,y,w,h,numOfInputs);
		addedComponents.add(ac);
		this.add((AndComponentGraphics) addedComponents.get(addedComponents.size()-1));
		this.setComponentZOrder(addedComponents.get(addedComponents.size()-1),0);
	}
	/**
	 * Adds a NAND Gate onto the WorkArea.
	 * */
	public void addNandComponent(int x,int y, int w, int h,int numOfInputs){
		NandComponentGraphics nc =new NandComponentGraphics(mg,x,y,w,h,numOfInputs);
		addedComponents.add(nc);
		this.add((NandComponentGraphics) addedComponents.get(addedComponents.size()-1));
		this.setComponentZOrder(addedComponents.get(addedComponents.size()-1),0);
	}
	/**
	 * Adds an OR Gate onto the WorkArea.
	 * */
	public void addOrComponent(int x,int y, int w, int h,int numOfInputs){
		OrComponentGraphics oc =new OrComponentGraphics(mg,x,y,w,h,numOfInputs);
		addedComponents.add(oc);
		this.add((OrComponentGraphics) addedComponents.get(addedComponents.size()-1));
		this.setComponentZOrder(addedComponents.get(addedComponents.size()-1),0);
	}
	/**
	 * Adds a NOR Gate onto the WorkArea.
	 * */
	public void addNorComponent(int x,int y, int w, int h,int numOfInputs){
		NorComponentGraphics nc =new NorComponentGraphics(mg,x,y,w,h,numOfInputs);
		addedComponents.add(nc);
		this.add((NorComponentGraphics) addedComponents.get(addedComponents.size()-1));
		this.setComponentZOrder(addedComponents.get(addedComponents.size()-1),0);
	}
	/**
	 * Adds a BUFFER Gate onto the WorkArea.
	 * */
	public void addBufferComponent(int x,int y, int w, int h,int numOfInputs){
		BufferComponentGraphics bc =new BufferComponentGraphics(mg,x,y,w,h,numOfInputs);
		addedComponents.add(bc);
		this.add((BufferComponentGraphics) addedComponents.get(addedComponents.size()-1));
		this.setComponentZOrder(addedComponents.get(addedComponents.size()-1),0);
	}
	/**
	 * Adds a NOT Gate onto the WorkArea.
	 * */
	public void addNotComponent(int x,int y, int w, int h,int numOfInputs){
		NotComponentGraphics nc =new NotComponentGraphics(mg,x,y,w,h,numOfInputs);
		addedComponents.add(nc);
		this.add((NotComponentGraphics) addedComponents.get(addedComponents.size()-1));
		this.setComponentZOrder(addedComponents.get(addedComponents.size()-1),0);
	}
	/**
	 * Adds an XOR Gate onto the WorkArea.
	 * */
	public void addXOrComponent(int x,int y, int w, int h,int numOfInputs){
		XorComponentGraphics xc =new XorComponentGraphics(mg,x,y,w,h,numOfInputs);
		addedComponents.add(xc);
		this.add((XorComponentGraphics) addedComponents.get(addedComponents.size()-1));
		this.setComponentZOrder(addedComponents.get(addedComponents.size()-1),0);
	}
	/**
	 * Adds an XNOR Gate onto the WorkArea.
	 * */
	public void addXNorComponent(int x,int y, int w, int h,int numOfInputs){
		XnorComponentGraphics xc =new XnorComponentGraphics(mg,x,y,w,h,numOfInputs);
		addedComponents.add(xc);
		this.add((XnorComponentGraphics) addedComponents.get(addedComponents.size()-1));
		this.setComponentZOrder(addedComponents.get(addedComponents.size()-1),0);
	}
	/**
	 * Adds a TRI-STATE BUFFER Gate onto the WorkArea.
	 * */
	public void addTSBufferComponent(int x,int y, int w, int h,int numOfInputs){
		TSBufferComponentGraphics tc =new TSBufferComponentGraphics(mg,x,y,w,h,numOfInputs);
		addedComponents.add(tc);
		this.add((TSBufferComponentGraphics) addedComponents.get(addedComponents.size()-1));
		this.setComponentZOrder(addedComponents.get(addedComponents.size()-1),0);
	}
	/**
	 * Adds a NODE Component onto the WorkArea.
	 * */
	public void addNodeComponent(int x,int y, int w, int h,int numOfInputs,int numOfOutputs){
		NodeComponentGraphics nc =new NodeComponentGraphics(mg,x,y,w,h,numOfInputs,numOfOutputs);
		addedComponents.add(nc);
		this.add((NodeComponentGraphics) addedComponents.get(addedComponents.size()-1));
		this.setComponentZOrder(addedComponents.get(addedComponents.size()-1),0);
	}
	/**
	 * Adds a D-FLIP-FLOP Gate onto the WorkArea.
	 * */
	public void addDFFComponent(int x,int y, int w, int h,int numOfInputs,int numOfOutputs){
		DFFComponentGraphics nc =new DFFComponentGraphics(mg,x,y,w,h,numOfInputs,numOfOutputs);
		addedComponents.add(nc);
		this.add((DFFComponentGraphics) addedComponents.get(addedComponents.size()-1));
		this.setComponentZOrder(addedComponents.get(addedComponents.size()-1),0);
	}
	/**
	 * Adds a T-FLIP-FLOP Gate onto the WorkArea.
	 * */
	public void addTFFComponent(int x,int y, int w, int h,int numOfInputs,int numOfOutputs){
		TFFComponentGraphics nc =new TFFComponentGraphics(mg,x,y,w,h,numOfInputs,numOfOutputs);
		addedComponents.add(nc);
		this.add((TFFComponentGraphics) addedComponents.get(addedComponents.size()-1));
		this.setComponentZOrder(addedComponents.get(addedComponents.size()-1),0);
	}
	/**
	 * Adds a JK-FLIP-FLOP Gate onto the WorkArea.
	 * */
	public void addJKFFComponent(int x,int y, int w, int h,int numOfInputs,int numOfOutputs){
		JKFFComponentGraphics nc =new JKFFComponentGraphics(mg,x,y,w,h,numOfInputs,numOfOutputs);
		addedComponents.add(nc);
		this.add((JKFFComponentGraphics) addedComponents.get(addedComponents.size()-1));
		this.setComponentZOrder(addedComponents.get(addedComponents.size()-1),0);
	}
	/**
	 * Adds an SR-FLIP-FLOP Gate onto the WorkArea.
	 * */
	public void addSRFFComponent(int x,int y, int w, int h,int numOfInputs,int numOfOutputs){
		SRFFComponentGraphics nc =new SRFFComponentGraphics(mg,x,y,w,h,numOfInputs,numOfOutputs);
		addedComponents.add(nc);
		this.add((SRFFComponentGraphics) addedComponents.get(addedComponents.size()-1));
		this.setComponentZOrder(addedComponents.get(addedComponents.size()-1),0);
	}
	/**
	 * Adds a CUSTOM Gate onto the WorkArea.
	 * */
	public void addCustomComponent(int x,int y, int w, int h,int numOfInputs,
			int numOfOutputs,String text,int clockPin,boolean showDetails){
		CustomComponentGraphics nc =new CustomComponentGraphics(mg,x,y,w,h,numOfInputs,numOfOutputs,
				text,clockPin,showDetails);
		addedComponents.add(nc);
		this.add((CustomComponentGraphics) addedComponents.get(addedComponents.size()-1));
		this.setComponentZOrder(addedComponents.get(addedComponents.size()-1),0);
	}
	/**
	 * Adds a TEXT Component onto the WorkArea.
	 * */
	public void addTextComponent(int x,int y, int w, int h,String text){
		TextComponentGraphics nc =new TextComponentGraphics(mg,x,y,w,h,text);
		addedComponents.add(nc);
		this.add((TextComponentGraphics) addedComponents.get(addedComponents.size()-1));
		this.setComponentZOrder(addedComponents.get(addedComponents.size()-1),0);
	}
	/**
	 * Adds a MODULE Gate onto the WorkArea.
	 * */
	public void addModuleComponent(int x,int y, int w, int h,File moduleFile,boolean showDetails){
		ModuleComponentGraphics nc =new ModuleComponentGraphics(mg,x,y,w,h,moduleFile,showDetails);
		addedComponents.add(nc);
		this.add((ModuleComponentGraphics) addedComponents.get(addedComponents.size()-1));
		this.setComponentZOrder(addedComponents.get(addedComponents.size()-1),0);
	}
	/**
	 * Adds a SPLITTER Gate onto the WorkArea.
	 * */
	public void addSplitterComponent(int x,int y, int w, int h,int numOfInputs,int splitCount){
		
		SplitterComponentGraphics sc =new SplitterComponentGraphics(mg,x,y,w,h,numOfInputs,splitCount,1);
		SplitterComponentGraphics sc2 =new SplitterComponentGraphics(mg,x,y,w,h,0,numOfInputs-splitCount,2);
		addedComponents.add(sc);
		this.add((SplitterComponentGraphics) addedComponents.get(addedComponents.size()-1));
		this.setComponentZOrder(addedComponents.get(addedComponents.size()-1),0);
		
		addedComponents.add(sc2);
		this.add((SplitterComponentGraphics) addedComponents.get(addedComponents.size()-1));
		this.setComponentZOrder(addedComponents.get(addedComponents.size()-1),0);
	}
	/**
	 * Adds a GROUPER Gate onto the WorkArea.
	 * */
	public void addGrouperComponent(int x,int y, int w, int h,int numOfOutputs,int splitCount){
		
		GrouperComponentGraphics gc =new GrouperComponentGraphics(mg,x,y,w,h,numOfOutputs,splitCount,1);
		GrouperComponentGraphics gc2 =new GrouperComponentGraphics(mg,x,y,w,h,0,numOfOutputs-splitCount,2);
		addedComponents.add(gc);
		this.add((GrouperComponentGraphics) addedComponents.get(addedComponents.size()-1));
		this.setComponentZOrder(addedComponents.get(addedComponents.size()-1),0);
		
		addedComponents.add(gc2);
		this.add((GrouperComponentGraphics) addedComponents.get(addedComponents.size()-1));
		this.setComponentZOrder(addedComponents.get(addedComponents.size()-1),0);
	}
	/**
	 * Draws the dotted grid onto the WorkArea.
	 * */
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		
		float dash1[] = { 2.5f };
    	BasicStroke dashed = new BasicStroke(1.5f,
    	      BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, dash1, 0.0f);
    	
    	BasicStroke normalStroke = new BasicStroke(2f);
    	
    	Graphics2D g2 = (Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                             RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setStroke(dashed);
         
		Color gridColor = Color.getHSBColor((float)0.1,(float)0.1,(float)0.9);
		g.setColor(gridColor);
		
		if(showGrid){
			for (int x=0; x<=getWidth(); x+=25) {
				g.drawLine(x,0, x,getHeight());
			}
			for (int y=0; y<=getHeight(); y+=25) {
				g.drawLine(0,y,getWidth(),y);
			}
		}
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                 RenderingHints.VALUE_ANTIALIAS_OFF);
		
		g2.setStroke(normalStroke);
	
	}
	/**
	 * Paints the SelectionBox onto the WorkArea.
	 * */
	public void paint(Graphics g){
		super.paint(g);
		
		float dash1[] = { 5.0f };
    	BasicStroke dashed = new BasicStroke(2.0f,
    	      BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, dash1, 0.0f);
    	
    	Graphics2D g2 = (Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                             RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setStroke(dashed);

        g2.setPaint(Color.blue);
        g2.draw(selectionBox);
	}
	/**
	 * Scans the WiringGrid for intersecting wires and places WireIntersectionPoints accordingly.
	 * */
	public void drawIntersections(){

		removeAllWireIntersections();

		//for each wire in the wires array
		for(int i=0;i<wiringGrid.getWires().size();i++){
			Wire w1=wiringGrid.getWires().get(i);
			//for each point in the wires array
			for(int j=0;j<wiringGrid.getWires().size();j++){
				//if wires are different
				if(i!=j){
					Wire w2=wiringGrid.getWires().get(j);
					ArrayList<Point> w1Points=w1.getPointsArray();
					ArrayList<Point> w2Points=w2.getPointsArray();
					
					//check if not grouped wires
					if(!(w1Points.get(0).equals(w2Points.get(0)) && 
							w1Points.get(w1Points.size()-1).equals(w2Points.get(w2Points.size()-1)))){
						
						//if both wires have first point in common (i.e. common pin)
						if(w1Points.get(0).equals(w2Points.get(0))){
							
							if(w1Points.get(1).equals(w2Points.get(1))){
								int a= w1Points.get(1).y;
								int b= w1Points.get(2).y;
								int c= w2Points.get(2).y;

								if((a>=b && a<=c) || (a>=c && a<=b)){
										addWireIntersectionPoint(w1Points.get(1));
								}
								else{
									if((b>=a && b<=c) || (b>=c && b<=c)){
										if(w1.getWireSegments().size()==5 && w2.getWireSegments().size()==5){
											addWireIntersectionPoint(new Point(w1Points.get(2).x-4,w1Points.get(2).y-2));
										}
										else{
											addWireIntersectionPoint(w1Points.get(2));
										}	
									}
									else{
										if((c>=a && c<=b) || (c>=b && c<=a)){
											if(w1.getWireSegments().size()==5 && w2.getWireSegments().size()==5){
												addWireIntersectionPoint(new Point(w2Points.get(2).x-4,w2Points.get(2).y-2));
											}
											else{
												addWireIntersectionPoint(w2Points.get(2));
											}
										}
									}
								}
							}
							else{
								if(w1Points.get(1).x<w2Points.get(1).x){
										addWireIntersectionPoint(w1Points.get(1));
								}
								else{
									if(w1Points.get(1).x>w2Points.get(1).x){
											addWireIntersectionPoint(w2Points.get(1));
									}
								}
							}
						}
					}
				}
			}
		}
		repaint();
	}
	/**
	 * Adds WireGroupDisplays onto grouped Wires.
	 * */
	public void drawWireGroupDisplays(){
		removeAllWireGroupDisplays();
		
		ArrayList<ComponentGraphics> flaggedComponents= new ArrayList<ComponentGraphics>();
		
		//for each wire in the wires array
		for(int i=0;i<wiringGrid.getWires().size();i++){
			Wire w1=wiringGrid.getWires().get(i);
			if(w1.isGrouped()){
				if(!flaggedComponents.contains(w1.getSecondPin().getParentComponent())){
					
					WireSegment ws= w1.getWireSegments().get(0);
					int xLoc=ws.getX()-15+ws.getWidth()/2;
					int yLoc=ws.getY()-15;
					int groupedCount=w1.getFirstPin().getGroupCount();
					
					addWireGroupDisplay(xLoc,yLoc,groupedCount);
					flaggedComponents.add(w1.getSecondPin().getParentComponent());
				}
				WireSegment ws2= w1.getWireSegments().get(w1.getWireSegments().size()-1);
				int xLoc=ws2.getX()-15+ws2.getWidth()/2;
				int yLoc=ws2.getY()-15;
				int groupedCount=w1.getFirstPin().getGroupCount();
				
				addWireGroupDisplay(xLoc,yLoc,groupedCount);
			}
		}
		repaint();
	}
	/**
	 * Copies the components from the WorkArea and saves them to an image file.
	 * */
	public void drawImage(){
		hideSelectionBox();
		deselectAllComponents();
		
		if(addedComponents.size()>0){
			int minX=getWidth();
			int minY=getHeight();
			int maxX=0;
			int maxY=0;
			for(int i=0;i<addedComponents.size();i++){
				if(addedComponents.get(i).getX()<minX){
					minX=addedComponents.get(i).getX();
				}
				if(addedComponents.get(i).getY()<minY){
					minY=addedComponents.get(i).getY();
				}
				if((addedComponents.get(i).getX()+addedComponents.get(i).getWidth())>maxX){
					maxX=addedComponents.get(i).getX()+addedComponents.get(i).getWidth();
				}
				if((addedComponents.get(i).getY()+addedComponents.get(i).getHeight())>maxY){
					maxY=addedComponents.get(i).getY()+addedComponents.get(i).getHeight();
				}
			}
			for(int i=0;i<getWiringGrid().getWires().size();i++){
				Wire w = wiringGrid.getWires().get(i);
				for(int j=0;j<w.getWireSegments().size();j++){
					WireSegment ws=w.getWireSegments().get(j);
					
					if(ws.getX()<minX){
						minX=ws.getX();
					}
					if(ws.getY()<minY){
						minY=ws.getY();
					}
					if((ws.getX()+ws.getWidth())>maxX){
						maxX=ws.getX()+ws.getWidth();
					}
					if((ws.getY()+ws.getHeight())>maxY){
						maxY=ws.getY()+ws.getHeight();
					}
				}
			}
			
			BufferedImage bi = new BufferedImage(getWidth()+100,getHeight()+100, BufferedImage.TYPE_INT_ARGB); 
			
			Graphics2D g = bi.createGraphics();
			showGrid=false;
			setOpaque(false);
			this.paint(g);
			showGrid=true;
			setOpaque(true);
			
			bi=bi.getSubimage(minX, minY, maxX-minX, maxY-minY);
			g.dispose();
			
			JFileChooser jf = new JFileChooser();
			jf.setDialogTitle("Save image as...");
			jf.addChoosableFileFilter(new PNGFileFilter());
			jf.setVisible(true);
			
			try{
				
				File imageFile = null;
				if (jf.showDialog(null,"Save") == JFileChooser.APPROVE_OPTION)
				{
					imageFile = jf.getSelectedFile();
				}
				
				String path = imageFile.getAbsolutePath();
				if(!path.endsWith(".png")){
					imageFile = new File(path + ".png");
				}
				ImageIO.write(bi,"png",imageFile);
				Desktop.getDesktop().open(imageFile);
			}
			catch (Exception e){}
		}
	}
	/**
	 * Returns the WiringGrid.
	 * @return WiringGrid
	 * */
	public WiringGrid getWiringGrid(){
		return wiringGrid;
	}
	/**
	 * Returns all the components that are added onto the WorkArea.
	 * @return ArrayList
	 * */
	public ArrayList<ComponentGraphics> getAddedComponents(){
		return addedComponents;
	}
	/**
	 * Hides the SelectionBox.
	 * */
	public void hideSelectionBox(){
		selectionBox.setSize(0,0);
		repaint();
	}
	/**
	 * Sets the added components to be not selected.
	 * */
	public void deselectAllComponents(){
		for(int i=0;i<addedComponents.size();i++){
			addedComponents.get(i).deselect();
		}
		repaint();
	}
	/**
	 * Adjusts the SelectionBox's Area to only contain the total area of all selected components. 
	 * */
	public void adjustSelectionBox(){
		Point adjustedMinPoint=new Point(getWidth(),getHeight());
		Point adjustedMaxPoint=new Point(0,0);
		boolean selectedSomething=false;
		for(int i=0;i<addedComponents.size();i++){
			
			if(addedComponents.get(i).isSelected()){
				selectedSomething=true;
				
				Point componentStartPoint = addedComponents.get(i).getLocation();
				Point componentEndPoint = addedComponents.get(i).getLocation();
				
				componentEndPoint.x+=addedComponents.get(i).getWidth();
				componentEndPoint.y+=addedComponents.get(i).getHeight();
				
				if(componentStartPoint.x<adjustedMinPoint.x){
					adjustedMinPoint.x=componentStartPoint.x;
				}
				if(componentStartPoint.y<adjustedMinPoint.y){
					adjustedMinPoint.y=componentStartPoint.y;
				}
				if(componentEndPoint.x>adjustedMaxPoint.x){
					adjustedMaxPoint.x=componentEndPoint.x;
				}
				if(componentEndPoint.y>adjustedMaxPoint.y){
					adjustedMaxPoint.y=componentEndPoint.y;
				}
			}
		}
		if(selectedSomething){
			selectionBoxStartPoint.x=adjustedMinPoint.x;
			selectionBoxStartPoint.y=adjustedMinPoint.y;
			selectionBoxEndPoint.x=adjustedMaxPoint.x;
			selectionBoxEndPoint.y=adjustedMaxPoint.y;
			selectionBox.setFrameFromDiagonal(selectionBoxStartPoint,selectionBoxEndPoint);
		}
		if(!selectedSomething){
			hideSelectionBox();
		}
	}
	@Override
	public void mousePressed(MouseEvent e) {
		
		mg.getAboutPanel().setVisible(false);
		
		if(mg.getActions().getCurrentAction()==1){
			selectionBoxStartPoint= e.getPoint();
			selectionBoxEndPoint = e.getPoint();
			selectionBoxEndPoint.x+=1;
			selectionBoxEndPoint.y+=1;
			selectionBox.setFrameFromDiagonal(selectionBoxStartPoint,selectionBoxEndPoint);
			for(int i=0;i<addedComponents.size();i++){
				if(addedComponents.get(i).checkIfSelected(selectionBox)){
					selectionBoxStartPoint=addedComponents.get(i).getLocation();
					selectionBoxEndPoint.x=addedComponents.get(i).getLocation().x+
							addedComponents.get(i).getWidth();
					selectionBoxEndPoint.y=addedComponents.get(i).getLocation().y+
							addedComponents.get(i).getHeight();
					selectionBox.setFrameFromDiagonal(selectionBoxStartPoint,selectionBoxEndPoint);
					setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
					mg.getActions().setActionToMove();
				}
			}
			
			repaint();
		}
		if(mg.getActions().getCurrentAction()==2){	
			dragStartPoint= e.getPoint();
		}
		if(mg.getActions().getCurrentAction()==3){
			
			if(mg.getActions().getZoomFactor()<1.75){
				
				mg.getActions().setZoomFactor(mg.getActions().getZoomFactor()+0.25);
				
				int newWidthAndHeight= (int)(1500*mg.getActions().getZoomFactor());
				
				int newX=(int) (-e.getPoint().x*1.25)+405;
				int newY=(int) (-e.getPoint().y*1.25)+240;
				if(newX>0||newY>0){
					newX=0;
					newY=0;
				}
				setBounds(newX,newY,newWidthAndHeight,newWidthAndHeight);
				mg.getVScrollBar().refreshBar();
				mg.getHScrollBar().refreshBar();
				for(int i =0;i<addedComponents.size();i++){
					addedComponents.get(i).zoomAdjust(mg.getActions().getZoomFactor());
				}
				adjustSelectionBox();
				
				for(int i=0;i<wiringGrid.getWires().size();i++){
					wiringGrid.getWires().get(i).maintainWire();
				}
				drawIntersections();
				drawWireGroupDisplays();
				repaint();
			}	
		}
		if(mg.getActions().getCurrentAction()==4){
			
			if(mg.getActions().getZoomFactor()>0.75){
				
				mg.getActions().setZoomFactor(mg.getActions().getZoomFactor()-0.25);
				
				int newWidthAndHeight= (int) (1500*mg.getActions().getZoomFactor());
				int newX=(int) (-e.getPoint().x/1.25)+405;
				int newY=(int) (-e.getPoint().y/1.25)+240;
				if(newX>0||newY>0){
					newX=0;
					newY=0;
				}
				setBounds(newX,newY,newWidthAndHeight,newWidthAndHeight);
				mg.getVScrollBar().refreshBar();
				mg.getHScrollBar().refreshBar();
				for(int i =0;i<addedComponents.size();i++){
					addedComponents.get(i).zoomAdjust(mg.getActions().getZoomFactor());
				}
				adjustSelectionBox();
				for(int i=0;i<wiringGrid.getWires().size();i++){
					wiringGrid.getWires().get(i).maintainWire();
				}
				drawIntersections();
				drawWireGroupDisplays();
				repaint();
			}
		}
		if(mg.getActions().getCurrentAction()==5){
			double zoomFactor=mg.getActions().getZoomFactor();
			
			int adjustedX=(int) (e.getX()/zoomFactor);
			int adjustedY=(int) (e.getY()/zoomFactor);
			
			if(adjustedX>(getWidth()-(75*zoomFactor))){
				adjustedX=(int) (getWidth()-(75*zoomFactor)-10);
			}
			if(adjustedY>(getHeight()-(50*zoomFactor))){
				adjustedY=(int) (getHeight()-(50*zoomFactor)-10);
			}
			//snap to grid
			adjustedX-=adjustedX%25;
			adjustedY-=adjustedY%25;
			
			addAndComponent(adjustedX,adjustedY,75,50,
					mg.getComponentPanel().getAndComponent().getNumberOfInputs());
			addedComponents.get(addedComponents.size()-1).zoomAdjust(zoomFactor);
			repaint();
		}
		if(mg.getActions().getCurrentAction()==8){
			double zoomFactor=mg.getActions().getZoomFactor();
			
			int adjustedX=(int) (e.getX()/zoomFactor);
			int adjustedY=(int) (e.getY()/zoomFactor);
			
			if(adjustedX>(getWidth()-(75*zoomFactor))){
				adjustedX=(int) (getWidth()-(75*zoomFactor)-10);
			}
			if(adjustedY>(getHeight()-(50*zoomFactor))){
				adjustedY=(int) (getHeight()-(50*zoomFactor)-10);
			}
			
			//snap to grid
			adjustedX-=adjustedX%25;
			adjustedY-=adjustedY%25;
			
			addNandComponent(adjustedX,adjustedY,75,50,
					mg.getComponentPanel().getNandComponent().getNumberOfInputs());
			addedComponents.get(addedComponents.size()-1).zoomAdjust(zoomFactor);
			repaint();
		}
		if(mg.getActions().getCurrentAction()==9){
			double zoomFactor=mg.getActions().getZoomFactor();
			
			int adjustedX=(int) (e.getX()/zoomFactor);
			int adjustedY=(int) (e.getY()/zoomFactor);
			
			if(adjustedX>(getWidth()-(75*zoomFactor))){
				adjustedX=(int) (getWidth()-(75*zoomFactor)-10);
			}
			if(adjustedY>(getHeight()-(50*zoomFactor))){
				adjustedY=(int) (getHeight()-(50*zoomFactor)-10);
			}
			
			//snap to grid
			adjustedX-=adjustedX%25;
			adjustedY-=adjustedY%25;
			
			addOrComponent(adjustedX,adjustedY,75,50,
					mg.getComponentPanel().getOrComponent().getNumberOfInputs());
			addedComponents.get(addedComponents.size()-1).zoomAdjust(zoomFactor);
			repaint();
		}
		if(mg.getActions().getCurrentAction()==10){
			double zoomFactor=mg.getActions().getZoomFactor();
			
			int adjustedX=(int) (e.getX()/zoomFactor);
			int adjustedY=(int) (e.getY()/zoomFactor);
			
			if(adjustedX>(getWidth()-(75*zoomFactor))){
				adjustedX=(int) (getWidth()-(75*zoomFactor)-10);
			}
			if(adjustedY>(getHeight()-(50*zoomFactor))){
				adjustedY=(int) (getHeight()-(50*zoomFactor)-10);
			}
			
			//snap to grid
			adjustedX-=adjustedX%25;
			adjustedY-=adjustedY%25;
			
			addNorComponent(adjustedX,adjustedY,75,50,
					mg.getComponentPanel().getNorComponent().getNumberOfInputs());
			addedComponents.get(addedComponents.size()-1).zoomAdjust(zoomFactor);
			repaint();
		}
		if(mg.getActions().getCurrentAction()==11){
			double zoomFactor=mg.getActions().getZoomFactor();
			
			int adjustedX=(int) (e.getX()/zoomFactor);
			int adjustedY=(int) (e.getY()/zoomFactor);
			
			if(adjustedX>(getWidth()-(75*zoomFactor))){
				adjustedX=(int) (getWidth()-(75*zoomFactor)-10);
			}
			if(adjustedY>(getHeight()-(50*zoomFactor))){
				adjustedY=(int) (getHeight()-(50*zoomFactor)-10);
			}
			
			//snap to grid
			adjustedX-=adjustedX%25;
			adjustedY-=adjustedY%25;
			
			addNotComponent(adjustedX,adjustedY,75,50,
					mg.getComponentPanel().getNotComponent().getNumberOfInputs());
			addedComponents.get(addedComponents.size()-1).zoomAdjust(zoomFactor);
			repaint();
		}
		if(mg.getActions().getCurrentAction()==12){
			double zoomFactor=mg.getActions().getZoomFactor();
			
			int adjustedX=(int) (e.getX()/zoomFactor);
			int adjustedY=(int) (e.getY()/zoomFactor);
			
			if(adjustedX>(getWidth()-(75*zoomFactor))){
				adjustedX=(int) (getWidth()-(75*zoomFactor)-10);
			}
			if(adjustedY>(getHeight()-(50*zoomFactor))){
				adjustedY=(int) (getHeight()-(50*zoomFactor)-10);
			}
			
			//snap to grid
			adjustedX-=adjustedX%25;
			adjustedY-=adjustedY%25;
			
			addBufferComponent(adjustedX,adjustedY,75,50,
					mg.getComponentPanel().getBufferComponent().getNumberOfInputs());
			addedComponents.get(addedComponents.size()-1).zoomAdjust(zoomFactor);
			repaint();
		}
		if(mg.getActions().getCurrentAction()==13){
			double zoomFactor=mg.getActions().getZoomFactor();
			
			int adjustedX=(int) (e.getX()/zoomFactor);
			int adjustedY=(int) (e.getY()/zoomFactor);
			
			if(adjustedX>(getWidth()-(75*zoomFactor))){
				adjustedX=(int) (getWidth()-(75*zoomFactor)-10);
			}
			if(adjustedY>(getHeight()-(50*zoomFactor))){
				adjustedY=(int) (getHeight()-(50*zoomFactor)-10);
			}
			
			//snap to grid
			adjustedX-=adjustedX%25;
			adjustedY-=adjustedY%25;
			
			addXOrComponent(adjustedX,adjustedY,75,50,
					mg.getComponentPanel().getXorComponent().getNumberOfInputs());
			addedComponents.get(addedComponents.size()-1).zoomAdjust(zoomFactor);
			repaint();
		}
		if(mg.getActions().getCurrentAction()==14){
			double zoomFactor=mg.getActions().getZoomFactor();
			
			int adjustedX=(int) (e.getX()/zoomFactor);
			int adjustedY=(int) (e.getY()/zoomFactor);
			
			if(adjustedX>(getWidth()-(75*zoomFactor))){
				adjustedX=(int) (getWidth()-(75*zoomFactor)-10);
			}
			if(adjustedY>(getHeight()-(50*zoomFactor))){
				adjustedY=(int) (getHeight()-(50*zoomFactor)-10);
			}
			
			//snap to grid
			adjustedX-=adjustedX%25;
			adjustedY-=adjustedY%25;
			
			addXNorComponent(adjustedX,adjustedY,75,50,
					mg.getComponentPanel().getXnorComponent().getNumberOfInputs());
			addedComponents.get(addedComponents.size()-1).zoomAdjust(zoomFactor);
			repaint();
		}
		if(mg.getActions().getCurrentAction()==15){
			double zoomFactor=mg.getActions().getZoomFactor();
			
			int adjustedX=(int) (e.getX()/zoomFactor);
			int adjustedY=(int) (e.getY()/zoomFactor);
			
			if(adjustedX>(getWidth()-(75*zoomFactor))){
				adjustedX=(int) (getWidth()-(75*zoomFactor)-10);
			}
			if(adjustedY>(getHeight()-(50*zoomFactor))){
				adjustedY=(int) (getHeight()-(50*zoomFactor)-10);
			}
			
			//snap to grid
			adjustedX-=adjustedX%25;
			adjustedY-=adjustedY%25;
			
			addTSBufferComponent(adjustedX,adjustedY,75,50,
					mg.getComponentPanel().getTSBufferComponent().getNumberOfInputs());
			addedComponents.get(addedComponents.size()-1).zoomAdjust(zoomFactor);
			repaint();
		}
		if(mg.getActions().getCurrentAction()==16){
			double zoomFactor=mg.getActions().getZoomFactor();
			
			int adjustedX=(int) (e.getX()/zoomFactor);
			int adjustedY=(int) (e.getY()/zoomFactor);
			
			if(adjustedX>(getWidth()-(15*zoomFactor))){
				adjustedX=(int) (getWidth()-(15*zoomFactor)-10);
			}
			if(adjustedY>(getHeight()-(17*zoomFactor))){
				adjustedY=(int) (getHeight()-(17*zoomFactor)-10);
			}
			
			//snap to grid
			adjustedX-=adjustedX%25;
			adjustedY-=adjustedY%25;
			
			addNodeComponent(adjustedX,adjustedY,15,17,mg.getComponentPanel()
					.getNodeComponent().getNumberOfInputs(),mg.getComponentPanel()
					.getNodeComponent().getNumberOfOutputs());
			addedComponents.get(addedComponents.size()-1).zoomAdjust(zoomFactor);
			repaint();
		}
		if(mg.getActions().getCurrentAction()==17){
			selectionBoxStartPoint= e.getPoint();
			selectionBoxEndPoint = e.getPoint();
			selectionBoxEndPoint.x+=1;
			selectionBoxEndPoint.y+=1;
			selectionBox.setFrameFromDiagonal(selectionBoxStartPoint,selectionBoxEndPoint);
			for(int i=0;i<addedComponents.size();i++){
				if(addedComponents.get(i).checkIfSelected(selectionBox)){
					if(addedComponents.get(i).getClass().getSimpleName().equals("SplitterComponentGraphics")||
							addedComponents.get(i).getClass().getSimpleName().equals("GrouperComponentGraphics")){
						deleteComponent(addedComponents.get(i));
						deleteComponent(addedComponents.get(i));
					}
					else{
						deleteComponent(addedComponents.get(i));
					}
					
				}
			}
			hideSelectionBox();
			drawIntersections();
			drawWireGroupDisplays();
			repaint();
		}
		if(mg.getActions().getCurrentAction()==18){
			double zoomFactor=mg.getActions().getZoomFactor();
			
			int adjustedX=(int) (e.getX()/zoomFactor);
			int adjustedY=(int) (e.getY()/zoomFactor);
			
			if(adjustedX>(getWidth()-(100*zoomFactor))){
				adjustedX=(int) (getWidth()-(100*zoomFactor)-10);
			}
			if(adjustedY>(getHeight()-(75*zoomFactor))){
				adjustedY=(int) (getHeight()-(75*zoomFactor)-10);
			}
			
			//snap to grid
			adjustedX-=adjustedX%25;
			adjustedY-=adjustedY%25;
			
			addDFFComponent(adjustedX,adjustedY,100,75,
					mg.getComponentPanel().getDFFComponent().getNumberOfInputs(),
					mg.getComponentPanel().getDFFComponent().getNumberOfOutputs());
			addedComponents.get(addedComponents.size()-1).zoomAdjust(zoomFactor);
			repaint();
		}
		if(mg.getActions().getCurrentAction()==19){
			double zoomFactor=mg.getActions().getZoomFactor();
			
			int adjustedX=(int) (e.getX()/zoomFactor);
			int adjustedY=(int) (e.getY()/zoomFactor);
			
			if(adjustedX>(getWidth()-(100*zoomFactor))){
				adjustedX=(int) (getWidth()-(100*zoomFactor)-10);
			}
			if(adjustedY>(getHeight()-(75*zoomFactor))){
				adjustedY=(int) (getHeight()-(75*zoomFactor)-10);
			}
			
			//snap to grid
			adjustedX-=adjustedX%25;
			adjustedY-=adjustedY%25;
			
			addTFFComponent(adjustedX,adjustedY,100,75,
					mg.getComponentPanel().getTFFComponent().getNumberOfInputs(),
					mg.getComponentPanel().getTFFComponent().getNumberOfOutputs());
			addedComponents.get(addedComponents.size()-1).zoomAdjust(zoomFactor);
			repaint();
		}
		if(mg.getActions().getCurrentAction()==20){
			double zoomFactor=mg.getActions().getZoomFactor();
			
			int adjustedX=(int) (e.getX()/zoomFactor);
			int adjustedY=(int) (e.getY()/zoomFactor);
			
			if(adjustedX>(getWidth()-(100*zoomFactor))){
				adjustedX=(int) (getWidth()-(100*zoomFactor)-10);
			}
			if(adjustedY>(getHeight()-(75*zoomFactor))){
				adjustedY=(int) (getHeight()-(75*zoomFactor)-10);
			}
			
			//snap to grid
			adjustedX-=adjustedX%25;
			adjustedY-=adjustedY%25;
			
			addJKFFComponent(adjustedX,adjustedY,100,75,
					mg.getComponentPanel().getJKFFComponent().getNumberOfInputs(),
					mg.getComponentPanel().getJKFFComponent().getNumberOfOutputs());
			addedComponents.get(addedComponents.size()-1).zoomAdjust(zoomFactor);
			repaint();
		}
		if(mg.getActions().getCurrentAction()==21){
			double zoomFactor=mg.getActions().getZoomFactor();
			
			int adjustedX=(int) (e.getX()/zoomFactor);
			int adjustedY=(int) (e.getY()/zoomFactor);
			
			if(adjustedX>(getWidth()-(100*zoomFactor))){
				adjustedX=(int) (getWidth()-(100*zoomFactor)-10);
			}
			if(adjustedY>(getHeight()-(75*zoomFactor))){
				adjustedY=(int) (getHeight()-(75*zoomFactor)-10);
			}
			
			//snap to grid
			adjustedX-=adjustedX%25;
			adjustedY-=adjustedY%25;
			
			addSRFFComponent(adjustedX,adjustedY,100,75,
					mg.getComponentPanel().getSRFFComponent().getNumberOfInputs(),
					mg.getComponentPanel().getSRFFComponent().getNumberOfOutputs());
			addedComponents.get(addedComponents.size()-1).zoomAdjust(zoomFactor);
			repaint();
		}
		if(mg.getActions().getCurrentAction()==22){
			double zoomFactor=mg.getActions().getZoomFactor();
			
			int adjustedX=(int) (e.getX()/zoomFactor);
			int adjustedY=(int) (e.getY()/zoomFactor);
			
			if(adjustedX>(getWidth()-(150*zoomFactor))){
				adjustedX=(int) (getWidth()-(150*zoomFactor)-10);
			}
			if(adjustedY>(getHeight()-(100*zoomFactor))){
				adjustedY=(int) (getHeight()-(100*zoomFactor)-10);
			}
			
			//snap to grid
			adjustedX-=adjustedX%25;
			adjustedY-=adjustedY%25;
			
			addCustomComponent(adjustedX,adjustedY,150,100,
					mg.getComponentPanel().getCustomComponent().getNumberOfInputs(),
					mg.getComponentPanel().getCustomComponent().getNumberOfOutputs(),
					mg.getComponentPanel().getCustomComponent().getComponentText(),
					mg.getComponentPanel().getCustomComponent().getClockPin(),
					mg.getComponentPanel().getCustomComponent().getShowDetailsValue());
			addedComponents.get(addedComponents.size()-1).zoomAdjust(zoomFactor);
			repaint();
		}
		if(mg.getActions().getCurrentAction()==23){
			double zoomFactor=mg.getActions().getZoomFactor();
			
			int adjustedX=(int) (e.getX()/zoomFactor);
			int adjustedY=(int) (e.getY()/zoomFactor);
			
			if(adjustedX>(getWidth()-(90*zoomFactor))){
				adjustedX=(int) (getWidth()-(90*zoomFactor)-10);
			}
			if(adjustedY>(getHeight()-(30*zoomFactor))){
				adjustedY=(int) (getHeight()-(30*zoomFactor)-10);
			}
			
			//snap to grid
			adjustedX-=adjustedX%25;
			adjustedY-=adjustedY%25;
			
			addTextComponent(adjustedX,adjustedY,90,30,
					mg.getComponentPanel().getTextComponent().getComponentText());
			addedComponents.get(addedComponents.size()-1).zoomAdjust(zoomFactor);
			repaint();
		}
		if(mg.getActions().getCurrentAction()==24){
			
			File f = mg.getComponentPanel().getModuleComponent().getFile();
			if(f!=null){
				double zoomFactor=mg.getActions().getZoomFactor();
				
				int adjustedX=(int) (e.getX()/zoomFactor);
				int adjustedY=(int) (e.getY()/zoomFactor);
				
				if(adjustedX>(getWidth()-(90*zoomFactor))){
					adjustedX=(int) (getWidth()-(90*zoomFactor)-10);
				}
				if(adjustedY>(getHeight()-(30*zoomFactor))){
					adjustedY=(int) (getHeight()-(30*zoomFactor)-10);
				}
				
				//snap to grid
				adjustedX-=adjustedX%25;
				adjustedY-=adjustedY%25;
				
				addModuleComponent(adjustedX,adjustedY,200,150,
						mg.getComponentPanel().getModuleComponent().getFile(),
						mg.getComponentPanel().getModuleComponent().getShowDetailsValue());
				addedComponents.get(addedComponents.size()-1).zoomAdjust(zoomFactor);
				repaint();
			}
		}
		if(mg.getActions().getCurrentAction()==25){
			double zoomFactor=mg.getActions().getZoomFactor();
			
			int adjustedX=(int) (e.getX()/zoomFactor);
			int adjustedY=(int) (e.getY()/zoomFactor);
			
			if(adjustedX>(getWidth()-(90*zoomFactor))){
				adjustedX=(int) (getWidth()-(90*zoomFactor)-10);
			}
			if(adjustedY>(getHeight()-(30*zoomFactor))){
				adjustedY=(int) (getHeight()-(30*zoomFactor)-10);
			}
			
			//snap to grid
			adjustedX-=adjustedX%25;
			adjustedY-=adjustedY%25;
			
			addSplitterComponent(adjustedX,adjustedY,100,100,
					mg.getComponentPanel().getSplitterGateInput(),mg.getComponentPanel().getSplitterGateOutput());
			addedComponents.get(addedComponents.size()-1).zoomAdjust(zoomFactor);
			addedComponents.get(addedComponents.size()-2).zoomAdjust(zoomFactor);
			repaint();
		}
		if(mg.getActions().getCurrentAction()==26){
			double zoomFactor=mg.getActions().getZoomFactor();
			
			int adjustedX=(int) (e.getX()/zoomFactor);
			int adjustedY=(int) (e.getY()/zoomFactor);
			
			if(adjustedX>(getWidth()-(90*zoomFactor))){
				adjustedX=(int) (getWidth()-(90*zoomFactor)-10);
			}
			if(adjustedY>(getHeight()-(30*zoomFactor))){
				adjustedY=(int) (getHeight()-(30*zoomFactor)-10);
			}
			
			//snap to grid
			adjustedX-=adjustedX%25;
			adjustedY-=adjustedY%25;
			
			addGrouperComponent(adjustedX,adjustedY,100,100,
					mg.getComponentPanel().getGrouperGateOutput(),mg.getComponentPanel().getGrouperGateInput());
			addedComponents.get(addedComponents.size()-1).zoomAdjust(zoomFactor);
			addedComponents.get(addedComponents.size()-2).zoomAdjust(zoomFactor);
			repaint();
		}
	}
	@Override
	public void mouseClicked(MouseEvent e) {}
	@Override
	public void mouseEntered(MouseEvent e) {
		if(mg.getActions().getCurrentAction()==1){
			setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==2){
			setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==3){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==4){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==5){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==6){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==7){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==8){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==9){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==10){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==11){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==12){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==13){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==14){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==15){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==16){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==17){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==18){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==19){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==20){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==21){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==22){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==23){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==24){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==25){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		if(mg.getActions().getCurrentAction()==26){
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
	}
	@Override
	public void mouseExited(MouseEvent e) {}
	@Override
	public void mouseReleased(MouseEvent e) {	
		if(mg.getActions().getCurrentAction()==1){
			adjustSelectionBox();
			repaint();
		}	
	}
	@Override
	public void mouseDragged(MouseEvent e) {
		if(mg.getActions().getCurrentAction()==1){
			
			selectionBoxEndPoint = e.getPoint();
			if(selectionBoxStartPoint.x==selectionBoxEndPoint.x){
				selectionBoxEndPoint.x+=1;
			}
			if(selectionBoxStartPoint.y==selectionBoxEndPoint.y){
				selectionBoxEndPoint.y+=1;
			}
			int pointX=(int)e.getPoint().getX();
			int pointY=(int)e.getPoint().getY();
			
			if(pointX>getWidth()-10)
				selectionBoxEndPoint.x=getWidth()-10;
			if(pointX<0)
				selectionBoxEndPoint.x=0+4;
			if(pointY>getHeight()-10)
				selectionBoxEndPoint.y=getHeight()-10;
			if(pointY<0)
				selectionBoxEndPoint.y=0+4;
			
			selectionBox.setFrameFromDiagonal(selectionBoxStartPoint,selectionBoxEndPoint);
			
			for(int i=0;i<addedComponents.size();i++){
				addedComponents.get(i).checkIfSelected(selectionBox);
			}
			repaint();
		}
		if(mg.getActions().getCurrentAction()==2){
		
			Rectangle selectionBoxClone=new Rectangle(selectionBox);
			boolean canTranslateX=true;
			boolean canTranslateY=true;
			
			dragEndPoint = e.getPoint();
			int desiredTranslationX= dragEndPoint.x-dragStartPoint.x;
			int desiredTranslationY= dragEndPoint.y-dragStartPoint.y;
			
			selectionBoxClone.translate(desiredTranslationX, desiredTranslationY);
			
			if(selectionBoxClone.getLocation().x<0){
				desiredTranslationX=-selectionBox.getLocation().x;
				canTranslateX=false;
			}
			if((selectionBoxClone.getLocation().x+selectionBoxClone.getWidth())>getWidth()-10){
				desiredTranslationX=(int)((getWidth()-10)-(selectionBox.getLocation().x+selectionBox.getWidth()));
				canTranslateX=false;
			}
			if(selectionBoxClone.getLocation().y<0){
				desiredTranslationY=-selectionBox.getLocation().y;
				canTranslateY=false;
			}
			if((selectionBoxClone.getLocation().y+selectionBoxClone.getHeight())>getHeight()-10){
				desiredTranslationY=(int)((getHeight()-10)-(selectionBox.getLocation().y+selectionBox.getHeight()));
				canTranslateY=false;
			}
			selectionBox.translate(desiredTranslationX, desiredTranslationY);
			for(int i=0;i<addedComponents.size();i++){
				if(addedComponents.get(i).isSelected()){
					addedComponents.get(i).moveToLocation(desiredTranslationX,desiredTranslationY);
				}
			}
			for(int j=0;j<wiringGrid.getWires().size();j++){
				Wire w= wiringGrid.getWires().get(j);
				
				if(w.areBothEndsSelected()){
					w.maintainWire();
					repaint();
				}else{
					if(w.isOnlyOneEndSelected()){
						removeWire(getWiringGrid().getWires().get(j));
						getWiringGrid().getWires().get(j).refreshWire();
						repaint();
					}
				}
			}	
			if(canTranslateX){
				dragStartPoint.x = e.getPoint().x;
			}
			if(canTranslateY){
				dragStartPoint.y = e.getPoint().y;
			}
		}
		drawIntersections();
		drawWireGroupDisplays();
		repaint();
	}
	@Override
	public void mouseMoved(MouseEvent e) {
		
		if(mg.getActions().getCurrentAction()==1){
			setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
			if(selectionBox.contains(e.getPoint())){
				mg.getActions().setActionToMove();
			}
		}
		if(mg.getActions().getCurrentAction()==2){
			setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
			if(!selectionBox.contains(e.getPoint())){
				mg.getActions().setActionToSelect();
			}
		}
		if(mg.getActions().getCurrentAction()==6){
			Graphics g1= getGraphics();
			g1.setColor(Color.green);
			
			if(mg.getActions().checkIfAddedFirstWirePoint()){
				if(mg.getActions().getFirstPin().getType()){
					
					g1.drawLine(mg.getActions().getFirstPin().getEndPoint().x,
							mg.getActions().getFirstPin().getEndPoint().y,e.getX(),e.getY());
					repaint();
				}else{
					if(!mg.getActions().getFirstPin().getType()){
						g1.drawLine(mg.getActions().getFirstPin().getStartPoint().x,
								mg.getActions().getFirstPin().getStartPoint().y,e.getX(),e.getY());
						repaint();
					}
				}
			}
		}
	}
}